#ifndef __METADATAOBJECTALLOCATOR_H__
#define __METADATAOBJECTALLOCATOR_H__

#include <iostream>
#include <mutex>
#include "cacheCommon.h"
#include "cacheThread.h"

struct allocatorStats
{
    allocatorStats()
    :in_use_(0)
    ,total_(0)
    {}
    size_t in_use_;
    size_t total_;
};

//内存池，链表数据结构
//使用申请的内存保存下一个内存块的地址
template <class T>
class metadataObjectAllocator 
{
public:
    metadataObjectAllocator()
    :freelist_(nullptr)
    {}

    //函数模版参数包，
    template<class...Args>
    T* New(Args&&... args)
    {
        size_t size = sizeof(T);
        if(size < 8)
            size = 8;

        T* res = LockAndAllocMemory(size);
        //调用构造函数，右值引用完美转发
        return new (res) T(std::forward<Args>(args)...);
    }

    T* LockAndAllocMemory(size_t size)
    {
        std::lock_guard<std::mutex> lc(lock_);

        T* res = freelist_;
        stats_.in_use_++;
        if(res == nullptr)
        {
            stats_.total_++;
            //向系统申请
            res = reinterpret_cast<T*>(systemAlloc(size));
            return res;
        }
        
        //保存下一个节点值
        freelist_ = reinterpret_cast<T*>(NextObj(freelist_));
        return res;
    }

    void Delete(T* p)
    {
       p->~T();
       LockAndDeleteMemory(p);
    }

    void LockAndDeleteMemory(T* p)
    {
        std::lock_guard<std::mutex> lc(lock_);

        NextObj(p) = freelist_;
        //*(reinterpret_cast<void**>(p)) = freelist_;
        freelist_ = p;
        stats_.in_use_--;
    }

private:
    T* freelist_;
    allocatorStats stats_;
    std::mutex lock_;
};

extern metadataObjectAllocator<qSpan> span_allocator_;
extern metadataObjectAllocator<threadCache> threadcache_allocator_;

#endif 